'''
Case Type： 故障&可靠性测试
Case Name： 主备数据库切换过程中，停止主机数据库或者备机数据库；
Create At: 2020/07/20
@zou_jialiang0505328114
Descption:
步骤 1.启动主备数据库，判断数据库状态；
步骤 2.进程主备数据库切换；
步骤 3.切换的同时停止主机或者备机；
'''
import os
import unittest
import time
from yat.test import macro
from yat.test import Node
from testcase.utils.CommonSH import *
from testcase.utils.Common import Common
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from testcase.utils.ComThread import ComThread


class Deletaduit(unittest.TestCase):
    primary_sh = CommonSH('PrimaryDbUser')
    standby_1_sh = CommonSH('Standby1DbUser')
    standby_2_sh = CommonSH('Standby2DbUser')
    nodes_tuple = ('PrimaryDbUser', 'Standby1DbUser', 'Standby2DbUser')

    @RestartDbCluster(*nodes_tuple)
    def setUp(self):
        self.log = Logger()
        self.log.info('------------Opengauss_Reliability_Dbsys_Case151.py start------------')
        self.startCmd = f'source {macro.DB_ENV_PATH};gs_om -t start'
        self.statusCmd = f'source {macro.DB_ENV_PATH};gs_om -t status --detail'
        self.rootNode = Node()
        self.com = Common()
        self.Constant = Constant()
        self.primary_user_node = Node(node='PrimaryDbUser')
        self.primary_root_node = Node(node='PrimaryRoot')
        self.standby1_root_node = Node(node='Standby1Root')
        self.standby1_user_node = Node(node='Standby1DbUser')
        self.TPCC_PATH = macro.TPCC_PATH

    def test_startdb(self):
        self.log.info('进程主备数据库切换；')
        switch_thread_1 = ComThread(self.standby_1_sh.executeGsctl,
                                    args=('switchover', self.Constant.SWITCH_SUCCESS_MSG,))
        switch_thread_1.setDaemon(True)
        switch_thread_1.start()
        time.sleep(1)
        self.log.info('切换的同时停止主机；')
        msg1 = self.com.kill_pid(self.primary_root_node, 9)
        self.assertEqual(msg1, '')

        self.log.info('获取swithover执行结果')
        switch_thread_1.join(int(macro.TPCC_RUN_MAX_TIME) * 2)
        switch_result_1 = switch_thread_1.get_result()
        self.log.info(switch_result_1)
        self.primary_sh.getDbClusterStatus('status')
        if switch_result_1:
            self.log.info('kill主节点后swithover执行成功，执行refresh')
            refresh_msg = self.standby_1_sh.exec_refresh_conf()
            self.assertTrue(refresh_msg)

            self.log.info('启动原主节点')
            is_started = self.primary_sh.startDbInstance(mode="standby")
            self.assertTrue(is_started)
        else:
            self.log.info('启动主节点')
            is_started = self.primary_sh.startDbInstance(mode="primary")
            self.assertTrue(is_started)

            self.log.info('kill主节点导致swithover执行失败，再次执行swithover')
            switch_msg = self.standby_1_sh.executeGsctl('switchover', self.Constant.SWITCH_SUCCESS_MSG)
            self.assertTrue(switch_msg)

            self.log.info('执行refresh')
            refresh_msg = self.standby_1_sh.exec_refresh_conf()
            self.assertTrue(refresh_msg)

        db_status = self.primary_sh.getDbClusterStatus('status')
        self.assertTrue(db_status)

        self.log.info('执行tpcc业务')
        tpcc_result = self.com.startTPCC(self.standby1_root_node, self.TPCC_PATH)
        self.log.info(tpcc_result)
        self.assertIn(self.Constant.TPCC_SUCCESS_MSG, tpcc_result)

        # 校验刷脏页是否完成
        self.log.info('校验刷脏页是否完成')
        dirty_page_finshed_flag = self.standby_1_sh.check_whether_remain_dirty_page()
        self.assertTrue(dirty_page_finshed_flag)

        # 校验备机是否完成数据同步
        self.log.info('校验备机是否完成数据同步')
        flag_1 = self.primary_sh.check_data_consistency()
        self.assertTrue(flag_1)
        flag_2 = self.standby_2_sh.check_data_consistency()
        self.assertTrue(flag_2)

        self.log.info('进程主备数据库切换；')
        switch_thread_2 = ComThread(self.primary_sh.executeGsctl,
                                    args=('switchover', self.Constant.SWITCH_SUCCESS_MSG,))
        switch_thread_2.setDaemon(True)
        switch_thread_2.start()
        time.sleep(1)

        self.log.info('切换的同时停止备机；')
        msg1 = self.com.kill_pid(self.standby1_root_node, 9)
        self.assertEqual(msg1, '')

        self.log.info('获取swithover执行结果')
        switch_thread_2.join(int(macro.TPCC_RUN_MAX_TIME) * 2)
        switch_result_2 = switch_thread_2.get_result()
        self.log.info(switch_result_2)
        self.primary_sh.getDbClusterStatus('status')
        if switch_result_2:
            self.log.info('kill备节点后swithover执行成功，执行refresh')
            refresh_msg = self.primary_sh.exec_refresh_conf()
            self.assertTrue(refresh_msg)

            self.log.info('启动备节点')
            is_started = self.standby_1_sh.startDbInstance(mode='standby')
            self.assertTrue(is_started)
        else:
            self.log.info('启动备节点')
            is_started = self.standby_1_sh.startDbInstance(mode='primary')
            self.assertTrue(is_started)

            self.log.info('kill主节点导致swithover执行失败，再次执行swithover')
            switch_msg = self.primary_sh.executeGsctl('switchover', self.Constant.SWITCH_SUCCESS_MSG)
            self.assertTrue(switch_msg)

            self.log.info('执行refresh')
            refresh_msg = self.primary_sh.exec_refresh_conf()
            self.assertTrue(refresh_msg)

        db_status = self.primary_sh.getDbClusterStatus('status')
        self.assertTrue(db_status)

        self.log.info('执行tpcc业务')
        tpcc_result = self.com.startTPCC(self.primary_root_node, self.TPCC_PATH)
        self.log.info(tpcc_result)
        self.assertIn(self.Constant.TPCC_SUCCESS_MSG, tpcc_result)
        # 校验刷脏页是否完成
        self.log.info('校验刷脏页是否完成')
        dirty_page_finshed_flag = self.primary_sh.check_whether_remain_dirty_page()
        self.assertTrue(dirty_page_finshed_flag)

        # 校验备机是否完成数据同步
        self.log.info('校验备机是否完成数据同步')
        flag_1 = self.standby_1_sh.check_data_consistency()
        self.assertTrue(flag_1)
        flag_2 = self.standby_2_sh.check_data_consistency()
        self.assertTrue(flag_2)

    def tearDown(self):
        cmd = "cat /etc/hostname"
        primary_hostname = self.primary_root_node.sh(cmd).result()
        self.log.info(primary_hostname)
        self.log.info(self.primary_sh.getDbClusterStatus('detail'))
        if self.primary_sh.check_whether_need_switch(primary_hostname):
            self.log.info('执行swithover,还原主备')
            switch_msg = self.primary_sh.executeGsctl('switchover', self.Constant.SWITCH_SUCCESS_MSG)
            self.assertTrue(switch_msg)

            self.log.info('执行refresh')
            refresh_msg = self.primary_sh.exec_refresh_conf()
            self.assertTrue(refresh_msg)
        self.log.info(
            '------------------------------------reliability_dbsys151.py finish------------------------------------')
